现存项目 问题 分析 解决方案
October 26, 2020
在这里对在工作中的项目中代码,编码模式进行集中吐槽, 分析, 并提出各类解决方案的成本, 优劣点.
基础设施
- svn 项目管理, 没有分支, 所有人都在同一条主分支上开发. 这种线性的开发模式导致敏捷开发的循环被各种环境打破, 开发代码和生产环境代码常常混杂在同一个主分支中, 导致迭代的周期被固定, 已上线的 bug 难以 bugfix, 因为能不能上代码的问题,加大同事间沟通成本, 降低效率. 虽然, 公司正在逐步迁移到 gitlab 中, 但是, 也存在一定的问题. 首先, 没有统一的 gitflow, 一部分的项目和 svn 时期一样, 只有 master 一条分支. 大部分项目用的是 gitlab flow, 多少也算是一种进步. 第二, 以往的 svn 记录并没有保留下来, 对于这一点我是相当疑惑的. 只要稍微有些常理也知道如果没办法保留 commit 信息, 那迁移的成本是不是太高? 稍微搜索一下就会有解决方案. 我是没看到除我以外有人在迁移的同时花些时间考虑一下保留 svn commit.
- 代码质量管理方案欠缺, 以前是完全没有代码质量管理. 近期才添加了 eslint prettier 的支持. 但是…很可惜, 大量代码已经因为前期的质量方案问题, 已经造成代码风格百花齐放的局面, 要么忍受各种飘红的错误信息, 要么直接把 eslint prettier 关掉. 代码质量这东西, 我个人认为是非 0 即 1 的, 今天你能忍受一条错误, 明天你就能忍受第二条. 只能说, 终吃了基础设施落后的恶果, 现在要弥补这个缺陷, 可以抽个时间用 eslint fix 直接跑一遍, 将所有错误信息全部先 fix 掉, 但是这是不太可能的. 以现今代码项目规模来看, 大概有 10%(估算而已)的代码是需要人为修复, 不管怎么看, 这个代码量都太大. 另一种可能就是引入 lint-stage 的方案, 只对新提交的代码进行质量检测. 这个方案落地我是比较看好的, 虽然对我来说, 这个项目有没有质量管理, 其实都好像没太大意义. 对我而言, 这个项目重写的效率大于重构.
- 打包策略, 已知使用 gulp 打包 js, postCSS 编译 CSS. 没有好的现代打包机制, 直接影响整个前端基础设施的进步. 现代 bundler 如 webpack, rollup. 都是依赖模块化进行打包的. 而 gulp, 则天生不是用来打包 module like 的 JS 的. 要转换到 webpack, 就必须转向模块化. 这个迁移成本其实在我看来是可以接受的. webpack 和 rollup 都是入口导向的, gulp 则是以文件导向的, 其实两者转换并没有那么困难. 在以往的经验中, 这种迁移并没有很难, 在内部也有成功的先例.
- 社区建设, 以往社区的缺失直接导致工程师间交流出现障碍, 大家都闭门造车, 反复地造轮子, 浪费人力. 对于造轮子, 我一向是持保留意见的. 自己通过造轮子, 了解技术原理可以. 但是在有现存成熟方案的前提是, 自己搞一套上生产环境, 我觉得是一种非常不负责任的表现. 我非常不赞成工程师搞一套只能解决现状, 没有充分考虑未来变化的方案大干快上. 闭门造车的结果就是维护困难, 扩展困难, 迁移困难, 这些都是血一样的教训.你要知道工程师遇到的大部分问题都是别人遇到过的, 最起码, 你得知道别人是怎么解决问题, 站在巨人的肩膀上看问题, 解决问题, 才是一个工程师合格的修养.
社区缺乏的现状稍微有些减轻, 因为有 gitlab 存在. 但是工程师的开源项目经验太少, 没办法在内部推广自己的轮子. 这点确实是工程师经验的不足, 也是氛围的问题. 在未来需要持续改进.
我司一直在谈如何提升人效的问题. 其实加大对基础设施的投入, 也不失为一种高性价比提升人效的方法. 以我的经验, 最应该先做的是打包策略和 git 接入, git 接入成本会更高一些, 主要体现在 diff 和 commit, 未来维护的成本和沟通成本会有所降低. webpack 则是目前现代化前端的发动机, 有了 bundler, 对目前很多问题都可以更有效的解决, 这里列举一些
- esnext 支持, 支持更高标准的 JavaScript 语法.
- treeShaking 减少代码体积.
- 更方便引入私有库和额外库, 减少重复造轮子, 更好地维护依赖关系.
- 代码静态分析, 减少各种依赖错误.
- 更现代, 更快的编译, 更短的压缩代码时间.
- 引入测试框架.
- 更好的应对未来升级.
上面提到的这些, 其实都是现在主流的前端构建方案. 新进来的开发, 多少都有共识, 就是现存的工程化实在是太久了. 以上这些问题的解决方案, 有些我们已经在做了, 但是还做的不够好.
代码质量
CSS
- 随意的命名规则, 在各个项目中, 命名规则基本是 pascal, snake 等混用, 对怎么命名其实是没有太大约束力的, 这一点, 其实也没什么所谓.
- 缺失 CSS scoped, 大量覆盖性代码和重复代码, 这个问题是迄今为止我觉得 css 管理中最严重的问题. 为了大量互相覆盖的 css 代码,我们必须写更多的 css 代码去覆盖. 结果就是, css 越写越多, 换个环境, 瞬间就不一致, 因为你不知道到底原来引用了哪里的 css, 也不知道需要覆盖什么 css, 所以每次都需要直接复制一份在此基础上继续改, 进而使 css 代码量增加, 最后变成一坨意大利面, 越来越难维护. 这个问题.
- 过量的 CSS hack, 以前是为了兼容旧的浏览器, 所以必须要 hack. 但是现在已经不需要再兼容远古浏览器了, 兼容版本基本都是 ie9 起步, 过量的 hack 其实让 css 的正交性, 局部性, 可预测性都出现非常多的问题. 有时候有些 css 代码, 不知道有什么用, 但是又不敢删掉. 扩展起来, 又让人莫名其妙. 比如, 有时候应该用 flex 布局的地方, 各种用其他 table, grid, float 之类的 css 方法, 强行布局. 我觉得到了这个年代, flex 是已经可以不假思索直接就上的.
要解决 css 问题, 最好的方法还是引入有效的具有 css scope 属性的 css 集成方案, 比如 scoped css 或者 css module.类似 BEM 的方案, 其实我是不太看好的. BEM 并不是一种强制性规则, 对于写些简单 css 的后端工程师是一种负担, 即便对于有经验的前端工程师, 完整的 BEM 规则也显得非常多余, 间接提高工程师的心智负担. 在我司全面使用 vue 的环境下, 我觉得 scoped css 就是一个不错的选择
JS
先说一下现状,目前基本上所有的项目,都已经做了工程化的处理了。jzallsite,site,mobi 使用了自己编写的 jz-cli 的打包方案,mallapp 的方案暂时确定是 vite。
- 全局变量管理, 这一点是我觉得比较大的历史遗留问题了。现代前端工程师都知道,如果你要在代码中引用一个外部变量,你应该直接 import 这个变量,而不是将这个变量做成全局变量,然后在项目里肆意地引用。目前所有项目基本都有这个通病,大量地在顶层创建全局变量,然后再在其他地方引用。比较常见就是 SIte,MallApp,Mobi 全局变量。我在做 mallapp 工程化的时候就发现一些代码在无意间创建全局变量的。例如在顶层调用
var variable1 = 1
,或者更夸张,在某个地方在变量还没做声明的时候直接调用variable2 = 2
,这样的隐式全局变量声明,具有非常大的隐患。 - 跨 iframe 调用脚本,这种模式在 jzallsite 和 mobi 两个项目中非常常用,因为这两个项目在一个页面中至少会有 1 个 iframe(其实所有人都知道这是一种反模式,但几乎没人求变)。在里层的 iframe 经常会调用外层的页面的代码,这是一件非常违反代码松耦合原则的一件事,同时也是非常不可控的。
Common 通病
- svn base 项目管理, 没有分支, 所有人都在同一条主分支上开发, 极度残忍. 没有 code review 也不需要, 因为没有分支合并.
- 代码没有 format 直接提交, 这点尤其无语, 经常打开文档会出现空格, tab 混用的代码, 代码一长一短的, 实在寒心.
- global css 落后 gulp 打包. 全局污染非常严重.
- js 依然有落后 gulp 打包, 全局变量特别多, 依赖打包顺序. 按道理模块规范何其多, 但我们任性一个也不用.
- 过于简单的 workflow, 没有讨论的空间, 不需要 review, 基本我提交项目就照单全收.
- iframe base 调优困难, 重复引入依赖.
- 没有调优的概念, 能用就行.
- 重复造轮子, 造劣质轮子直接用于项目. 为什么不优先考虑行业成熟方案.我觉得是看的少, 不知道有成熟方案.
- 也是因为自己造轮子, 特质化, 没有标准. 引入方案困难.
- 没有注释标准. 反正想怎么写就怎么写, 更多的是直接不写, jsDoc 了解一下?
- 大量 hard coding, 纯手写 url, 不会用变量来管理吗\
- css 命名混乱, 有使用 camelCase 的, 有使用 snake 的, 有使用 underscore 的,
Mobi
- 粗暴迭代, 直接创建新文件
请看新时代 coding 风格, 面向复制新文件的编程风格. 需求风格 2.0 => 3.0 直接每个模块复制一段新的代码到 xxxV3.jsp.inc. 跟接着同样新赠 xxxV3.src.css, 维护水平指数上升, 极具文艺复兴特质. 在代码中到处可以看到 if(…ThemeV3) 的代码复用字样. 估计也是因为 2.0 代码太捞, 没办法实现 3.0 功能. 另 3.0 的主开发已经离职, 牛逼. 所以直接搞一套新的.虽然我目前写的代码也是面向复制新文件. 后面会再说到.
- 文艺复兴系列之 jquery
大量代码逻辑依赖 jQuery, 依赖于视图层. 就问你敢不敢动 dom 结构. 我感情 5, 6 年前没有 vue react angular. 前端的框架不是还有 ember 之流? 怎么想到直接一把梭子就是干?
给各位欣赏一下面向 jq 的响应式编程
我丢, 即便上个年代上模板引擎他不香吗. pug, handlebar, 那样是上个年代没有的, 即便在 java 端也有相应的模板引擎. 你直接给我 srcipt.append 是要玩什么? 拼接模板就拼接模板吧, 你能不能对齐? 来看看各种风格
实在是让人赏心悦目
Qz PC & Mall PC
-
引入整个 antd bundle
明明在 console 已经说了不要引入整个 antd 包, 但是依然整个包引入了. 公司原本使用自己的组件库, 貌似放弃了, 转而使用 antd-vue 了. 之后应该自己魔改了. 不过看了看 antd-vue 的代码貌似是全程使用 render + jsx. 这魔改难度略大. 毕竟这个 antd-vue 的版本就是 antd 魔改出来的.
-
全局风格
全局风格的实现在我看来也是相当下饭的操作. 使用内联 style 的架构. 风格效果全靠覆盖. 怎么, 大家是没听过 css-in-js 还是咋地. 以后每新建一个模块都要使用 window.globalcolor 来设置颜色和其他东西. 我谢谢你.
-
没有使用任何 state management 框架, 改数据全靠在全局变量上改.
我…都上 vue 了, 上 vuex 能把你咋地. 导致代码耦合已经相当严重. 到处都引用全局变量卧槽. 当然在其他项目这个也中招了. 数据保护不存在的, 想怎么改就怎么改.
- utils 只有一个文件, 目前已超过 10000+行. utils 和 api 全放这了, 这个文件能不大? 另外作为 utils 函数你不注释, 你是写给自己用的吗
Qz 小程序
迭代有些问题, 版本管理不是很明确, 这玩意在手机中常常会占用非常多的内存, 常常一打开就飙到 600m+, 要知道小程序的上限貌似只有 1G. 没仔细研究过代码, 按道理说不应该能占用这么多内存的. 可能是因为大量的 component 创建导致的. 另外需求也是不是很合理, 例如视频列表, 地图列表等, 其实是不应该可以插入多个这样的模块的. 这个项目 api 编写不是很规范, 而且里面有些异步代码没有回调, 没有考虑到连锁的异步场景, 典型的是登录的模块, 代码那是比较不科学. 状态管理的缺失也导致我开发全局订阅事件这样的库. 里面很多黑科技. 不过在公司众多项目中代码算是比较中规中矩了.